#include <string.h>
#include <stdio.h>

#include "config.h"
#include "nibble.h"

#ifdef QUIET_MODE
#define alert(dummy...)
#else
#define alert(fmtstr, args...) \
  (fprintf(stderr, PROGNAME ":%s: " fmtstr "\n", __func__, ##args))
#endif



nibbleContext *init_nibble(const char *schema_file)
{

  nibbleContext *nc = NULL;
  packedobjectsContext *pc = NULL;

  if ((nc = (nibbleContext *)malloc(sizeof(nibbleContext))) == NULL) {
    alert("Could not alllocate memory.");
    return NULL;
  }

  if ((pc = init_packedobjects(schema_file, 0, 0)) == NULL) {
    alert("failed to initialise libpackedobjects");
    return NULL;
  }

  nc->pc = pc;
  
  return nc;
  
}

void free_nibble(nibbleContext *nc)
{

  free_packedobjects(nc->pc);
  free(nc);
  
}

int tx_nibble(nibbleContext *nc, xmlDocPtr doc, int seconds) {

  packedobjectsContext *pc = nc->pc;
  unsigned char digits[MAX_NUM_DIGITS+1];
  char *pdu = NULL;
  size_t numdigits, bytes;
  
  pdu = packedobjects_encode(pc, doc);
  if (pc->bytes == -1) {
    alert("Failed to encode.\n");
    return pc->encode_error;
  }
  bytes = encapsulate_data(pdu, pc->bytes);
  //printf("bytes:%d\n", bytes);
  numdigits = data_to_dtmfdigits(digits, pdu, bytes);
  printf("transmitting %d digits:%s\n", numdigits, digits);
  mod_dtmf("/tmp/dtmf.raw", digits);
  playback_raw("/tmp/dtmf.raw", seconds);

  return bytes;
  
}


xmlDocPtr rx_nibble(nibbleContext *nc, int seconds)
{
  packedobjectsContext *pc = nc->pc;
  xmlDocPtr doc = NULL;
  unsigned char digits[MAX_NUM_DIGITS+1];
  unsigned char data[MAX_NUM_DIGITS/2+2];
  int numdigits = 0;
  size_t bytes;

  bzero(digits, MAX_NUM_DIGITS+1);
  
  record_raw("/tmp/recorded.raw", seconds);
  //printf("decoding .raw with spandsp\n");
  numdigits = demod_dtmf("/tmp/recorded.raw", digits);
  
  printf("received %d digits:%s\n", numdigits, digits);
  bytes = dtmfdigits_to_data(data, digits, numdigits);
  if (bytes) {
    bytes = unencapsulate_data(data, bytes);
    //printf("bytes:%d\n", bytes);
    if (bytes) {
      // this will need to be freed
      doc = packedobjects_decode(pc, data);
      if (pc->decode_error) alert("Failed to decode.\n");
    } else {
      alert("Checksum failed.\n");
    }
  }
  
  return doc;
}
